/*
 * 2D simplex noise, by Stefan Gustavsson
 */

/*
 * "permTexture" is a 256x256 texture that is used for both the permutations
 * and the 2D and 3D gradient lookup.
 */
uniform sampler2D permTexture, region1, region2, region3, region4;
uniform vec4 cameraPosition;
uniform float cameraAngle;
varying vec3 texCoord;
/*
 * To create offsets of one texel and one half texel in the
 * texture lookup, we need to know the texture image size.
 */
#define ONE 0.00390625
#define ONEHALF 0.001953125
// The numbers above are 1/256 and 0.5/256, change accordingly
// if you change the code to use another texture size.


// Skew and unskew factors are a bit hairy for 2D, so define them as constants
// This is (sqrt(3.0)-1.0)/2.0
#define F2 0.366025403784
// This is (3.0-sqrt(3.0))/6.0
#define G2 0.211324865405

float snoise(in vec2 P) {



	// Skew the (x,y) space to determine which cell of 2 simplices we're in
	float s = (P.x + P.y) * F2; // Hairy factor for 2D skewing
	vec2 Pi = floor(P + s);
	float t = (Pi.x + Pi.y) * G2; // Hairy factor for unskewing
	vec2 P0 = Pi - t; // Unskew the cell origin back to (x,y) space
	Pi = Pi * ONE + ONEHALF; // Integer part, scaled and offset for texture lookup

	vec2 Pf0 = P - P0; // The x,y distances from the cell origin

	// For the 2D case, the simplex shape is an equilateral triangle.
	// Find out whether we are above or below the x=y diagonal to
	// determine which of the two triangles we're in.
	vec2 o1;
	if (Pf0.x > Pf0.y)
		o1 = vec2(1.0, 0.0); // +x, +y traversal order
	else
		o1 = vec2(0.0, 1.0); // +y, +x traversal order

	// Noise contribution from simplex origin
	vec2 grad0 = texture2D(permTexture, Pi).rg * 4.0 - 1.0;
	float t0 = 0.5 - dot(Pf0, Pf0);
	float n0;
	if (t0 < 0.0)
		n0 = 0.0;
	else {
		t0 *= t0;
		n0 = t0 * t0 * dot(grad0, Pf0);
	}

	// Noise contribution from middle corner
	vec2 Pf1 = Pf0 - o1 + G2;
	vec2 grad1 = texture2D(permTexture, Pi + o1 * ONE).rg * 4.0 - 1.0;
	float t1 = 0.5 - dot(Pf1, Pf1);
	float n1;
	if (t1 < 0.0)
		n1 = 0.0;
	else {
		t1 *= t1;
		n1 = t1 * t1 * dot(grad1, Pf1);
	}

	// Noise contribution from last corner
	vec2 Pf2 = Pf0 - vec2(1.0 - 2.0 * G2);
	vec2 grad2 = texture2D(permTexture, Pi + vec2(ONE, ONE)).rg * 4.0 - 1.0;
	float t2 = 0.5 - dot(Pf2, Pf2);
	float n2;
	if (t2 < 0.0)
		n2 = 0.0;
	else {
		t2 *= t2;
		n2 = t2 * t2 * dot(grad2, Pf2);
	}

	// Sum up and scale the result to cover the range [-1,1]
	return 70.0 * (n0 + n1 + n2);
}


#define SAMPLEDIST 0.2

float sample(vec2 pos) {

	//pos.x = cos(-cameraAngle)*pos.x - sin(-cameraAngle)*pos.z;
	//pos.z = sin(-cameraAngle)*pos.x + cos(-cameraAngle)*pos.z;

	return 0.03 * snoise(pos) + .5 * abs(snoise(pos * 0.1)) + snoise(pos* 0.003);
}

void main() {
	vec3 normal, lightDir;
	vec4 diffuse, ambient, pos;
	float NdotL;

	//pos = gl_Vertex;
	vec4 pp = gl_Vertex;
	pos = pp;

	// by only having vertices in areas where the camera is looking we can increase
	// the framerate substantially.

	// rotate with camera rotation
	pos.x = pp.x * cos(cameraAngle) - pp.z * sin(cameraAngle);
	pos.z = pp.x * sin(cameraAngle) + pp.z * cos(cameraAngle);

	pos += cameraPosition;

	//pos = round(pos*100.)*.01;

	float noisemx = sample(pos.xz - vec2(SAMPLEDIST, 0.0));
	float noisepx = sample(pos.xz + vec2(SAMPLEDIST, 0.0));
	float noisemz = sample(pos.xz - vec2(0.0, SAMPLEDIST));
	float noisepz = sample(pos.xz + vec2(0.0, SAMPLEDIST));

	//pos -= cameraPosition;
	pos.y = gl_Vertex.y + .25 * (noisemx + noisepx + noisemz + noisepz);

	// calc normal based on noise heights
	float dx = (noisepx - noisemx) / (2. * SAMPLEDIST);
	float dz = (noisepz - noisemz) / (2. * SAMPLEDIST);
	normal = normalize(gl_NormalMatrix * vec3(-0, 1., -0));

	/* now normalize the light's direction. Note that according to the
	 OpenGL specification, the light is stored in eye space. Also since
	 we're talking about a directional light, the position field is actually
	 direction */
	lightDir = normalize(vec3(gl_LightSource[0].position));

	/* compute the cos of the angle between the normal and lights direction.
	 The light is directional so the direction is constant for every vertex.
	 Since these two are normalized the cosine is the dot product. We also
	 need to clamp the result to the [0,1] range. */

	NdotL = max(dot(normal, lightDir), 0.0);

	/* Compute the diffuse, ambient and globalAmbient terms */
	diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
	ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;

	//globalAmbient = gl_LightModel.ambient * gl_FrontMaterial.ambient;
	/* compute the specular term if NdotL is  larger than zero */
	//if (NdotL > 0.0 && gl_FrontMaterial.shininess > 0.0) {

	//	NdotHV = max(dot(normal, normalize(gl_LightSource[0].halfVector.xyz)),0.0);
	//	specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV,gl_FrontMaterial.shininess);
	//}

	texCoord = pos.xzy;
	texCoord.st *= .5;
	gl_FrontColor = NdotL * diffuse + ambient;// + specular + globalAmbient;
	gl_Position = gl_ProjectionMatrix * (gl_ModelViewMatrix * pos);

}
